package com.sxbbc.plat.service;

import com.sxbbc.common.basics.exceptions.ThrowJsonException;
import com.sxbbc.common.basics.service.redis.RedisUtilsService;
import com.sxbbc.common.basics.utils.calculation.CalcuUtils;
import com.sxbbc.common.core.dto.jz.FreezeDTO;
import com.sxbbc.common.core.dto.jz.FreezeVo;
import com.sxbbc.common.core.entity.jz.BFreezeMoneyDetail;
import com.sxbbc.common.core.entity.jz.CCustomer;
import com.sxbbc.common.core.entity.jz.CFreezeDonateDetail;
import com.sxbbc.common.core.entity.jz.CFreezePointDetail;
import com.sxbbc.common.core.enums.FreezeStatusEnums;
import com.sxbbc.common.core.enums.FreezeTypeEnums;
import com.sxbbc.common.core.enums.ParamEnums;
import com.sxbbc.common.core.mapper.jz.*;
import com.sxbbc.common.core.service.*;
import com.sxbbc.common.core.service.system.redis.RedisSeckillService;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sxbbc.common.basics.utils.statics.StaticUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 定时器处理 业务层
 * @author xiaoky
 * @date 2019-06-13
 */
@Service
public class TaskService {

	private static Logger logger = LogManager.getLogger(TaskService.class);

	@Autowired
	private ICCustomerService customerService;
	@Autowired
	private IActivitySeckillService activitySeckillService;
	@Autowired
	private IActivitySeckillDetailService activitySeckillDetailService;
	@Autowired
	private IProcMainService procMainService;
	@Autowired
	private IInfoParamService infoParamService;
	@Autowired
	private IActivitySeckillRemindService activitySeckillRemindService;
	@Autowired
	private IPushService pushService;
	@Autowired
	private RedisSeckillService redisSeckillService;
	@Autowired
	private RedisUtilsService redisUtilsService;
	@Autowired
	private ICConfigurationService icConfigurationService;
	@Autowired
	private IAccountChangeService accountChangeService;
	@Autowired
	private ICPushLogService icPushLogService;
	@Autowired
	private ActivitySeckillDetailMapper activitySeckillDetailMapper;
	@Autowired
	private CAccountMapper cAccountMapper;
	@Autowired
	private SysDealDataMapper sysDealDataMapper;
	@Autowired
	private SysDealDetailMapper sysDealDetailMapper;
	@Autowired
	private AgAccountMapper agAccountMapper;
	@Autowired
	private CFreezePointDetailMapper cFreezePointDetailMapper;
	@Autowired
	private BFreezeMoneyDetailMapper bFreezeMoneyDetailMapper;
	@Autowired
	private CFreezeDonateDetailMapper cFreezeDonateDetailMapper;
	@Autowired
	private OrderMainMapper orderMainMapper;
	
	/**
	 * 每日签到重置
	 */
	public void autoSignReset () {
		QueryWrapper<CCustomer> queryWrapper = new QueryWrapper<CCustomer>();
		queryWrapper.eq("sign", StaticUtils.STATUS_YES);
		CCustomer customer = new CCustomer();
		customer.setSign(StaticUtils.STATUS_NO);
		customerService.update(customer, queryWrapper);
	}

	/**
	 * 定时关闭秒杀活动
	 */
	//TODO 取消定时关闭秒杀活动
//	public void autoCloseSeckill() {
//		DateUtil dateUtil = DateUtil.getInstance();
//		//获取已超过当前时间且状态为有效的秒杀活动信息列表
//		QueryWrapper<ActivitySeckill> wrapper = new QueryWrapper<>();
//		wrapper.eq("status", StaticUtils.STATUS_YES).apply("date_format(over_time,'%Y-%m-%d %H:%i') < {0}",dateUtil.currentDate());
//		List<ActivitySeckill> list = activitySeckillService.list(wrapper);
//		//商品编码的集合，set去重
//		Set<String> proCodeSet = new HashSet<>();
//		//秒杀活动子表集合，更新状态
//		List<ActivitySeckillDetail> seckillDetailList = new ArrayList<>();
//		for (ActivitySeckill a : list) {
//			//秒杀活动主表状态变更为0
//			a.setStatus(StaticUtils.STATUS_NO);
//			QueryWrapper<ActivitySeckillDetail> dWrapper = new QueryWrapper<>();
//			dWrapper.eq("seckill_id",a.getId()).eq("status",StaticUtils.STATUS_YES);
//			List<ActivitySeckillDetail> dList = activitySeckillDetailService.list(dWrapper);
//			if (!CollectionUtils.isEmpty(dList)) {
//				for (ActivitySeckillDetail seckillDetail : dList) {
//				    //Redis清除秒杀信息
//					redisSeckillService.removeSkDetail(seckillDetail.getSkuId());
//					seckillDetail.setStatus(StaticUtils.STATUS_NO);
//					proCodeSet.add(seckillDetail.getProCode());
//					seckillDetailList.add(seckillDetail);
//				}
//			}
//		}
//		//秒杀信息表状态更新
//		if (!CollectionUtils.isEmpty(list)) {
//			activitySeckillService.updateBatchById(list);
//		}
//		//秒杀子表状态更新
//		if (!CollectionUtils.isEmpty(seckillDetailList)) {
//			activitySeckillDetailService.updateBatchById(seckillDetailList);
//		}
//		//商品表activitySign字段清除
//		List<ProcMain> proList = new ArrayList<>();
//		for (String proCode : proCodeSet) {
//			ProcMain procMain = procMainService.selectOneByProCode(proCode);
//			if (procMain != null) {
//				//当该商品没有活动的时候才清空activitySign字段
//				int count = activitySeckillDetailMapper.queryDoingSeckill(procMain.getProCode());
//				if (count == 0) {
//					procMain.setActivitySign("");
//					proList.add(procMain);
//				}
//			}
//		}
//		if (!CollectionUtils.isEmpty(proList)) {
//			procMainService.updateBatchById(proList);
//		}
//	}

	/**
	 * 定时提醒秒杀活动
	 */
	//TODO 取消定时提醒秒杀活动
//	public void autoRemind() {
//		//秒杀前多少分钟提醒
//		int minute = CalcuUtils.getInstance().getValueByClass(int.class,infoParamService.getValueByCode(ParamEnums.REMIND_TIME));
//		//需要提醒的集合
//		List<ActivitySeckillRemind> remindList = activitySeckillRemindService.queryNeedRemind(minute);
//		if (!CollectionUtils.isEmpty(remindList)) {
//			for (ActivitySeckillRemind r : remindList) {
//				//推送通知
//				//极光推送使用token作为alias 获取用户的token
//				String token = redisUtilsService.getKey(r.getCid() + "_token");
//				PushVo vo = new PushVo(token,MsgUtils.JPUSH_0007,PushTypeEnums.SECKILL_NOTICE.getId(),
//						String.valueOf(r.getSkuId()),new String[]{r.getProName(),String.valueOf(minute)},r.getCid());
//				pushService.pushMessageById(vo);
//				//已提醒的，变更状态
//				r.setStatus(StaticUtils.STATUS_NO);
//				activitySeckillRemindService.updateById(r);
//			}
//		}
//	}

	/**
	 * 每日计算交易数据
	 * @author leehao
	 */
//	public void autoCalPlatDealData() {
//		DateUtil dateUtil = DateUtil.getInstance();
//		logger.info("每日计算平台交易数据，开始时间：【 " + dateUtil.nowDate(dateUtil.DEFAULT_DATETIME_PATTERN) + " 】");
//		CalcuUtils calUtil = CalcuUtils.getInstance();
//		/* 1.获取系统参数 */
//		//1.1 获取转换的单元 如10000以上的贡献值才参与转换
//		//BigDecimal changeUnit = calUtil.getValueByClass(BigDecimal.class,infoParamService.getValueByCode(ParamEnums.DONATE_TO_UNIT));
//
//		/* 2.获取用户账户与代理账户满足条件的总数 */
//		//2.1 获取用户账户满足条件的总数
//		//BigDecimal customerDonate = cAccountMapper.sumTotalWithValid(changeUnit);
//		//2.2 获取代理账户满足条件的总数
//		//BigDecimal agentDonate = agAccountMapper.sumTotalWithValid(changeUnit);
//		//2.3 计算总贡献值=用户账户总数+代理账户总数
//		//BigDecimal totalDonate = calUtil.add(customerDonate,agentDonate,2);
//
//		/* 7月19日-7月20日改动 */
//        /* 统计出来的总贡献值，不再减去前一日的共享值 */
//
//        /*
//        *//* 3.上一日的数据进行计算 *//*
//        BigDecimal yesterdayUnit = BigDecimal.ZERO;
//        //3.1 拿到上一日的平台数据
//        SysDealData yesterdayDealData = sysDealDataMapper.selectLastOne();
//        if (yesterdayDealData != null && yesterdayDealData.getUnitTotal() != null) {
//            yesterdayUnit = yesterdayDealData.getUnitTotal();
//        }
//        //3.2 最终的共享值=本次总共享值-上一日发放的总共享值
//        BigDecimal finallyDonate = calUtil.sub(totalDonate,yesterdayUnit,2);
//        */
//
//		//3.3 本次单元共享值
//		//BigDecimal totalUnit = totalDonate.divide(changeUnit,0,BigDecimal.ROUND_FLOOR);
//		//3.4 保存记录主表
//		SysDealData dealData = new SysDealData();
//		dealData.setSendTotalDonate(totalDonate);
//		dealData.setSendTotalUnit(totalUnit);
//
//		/* 4.获取有效的贡献值账户(cid、donate) */
//        BigDecimal showUnit = BigDecimal.ZERO;
//		//4.2 获取有效的用户贡献值账户
//		List<DataVo> customerList = cAccountMapper.queryValidDonateList(changeUnit);
//		if (!CollectionUtils.isEmpty(customerList)) {
//			for (DataVo d : customerList) {
//				SysDealDetail dealDetail = new SysDealDetail();
//				dealDetail.setCid(d.getCid());
//				dealDetail.setTotalDonate(d.getDonate());
//				//3.3 每个用户转换后的单元共享值
//				BigDecimal customerUnit = d.getDonate().divide(changeUnit,0,BigDecimal.ROUND_FLOOR);
//				dealDetail.setUnitShare(customerUnit);
//				dealDetail.setType(StaticUtils.CUSTOMER_ACCOUNT_SUM);
//                showUnit = calUtil.add(showUnit,customerUnit,0);
//                logger.info("分红查询Cid"+d.getCid());
//				sysDealDetailMapper.insert(dealDetail);
//			}
//		}
//		//4.3 获取有效的代理贡献值账户
//		List<DataVo> agentList = agAccountMapper.queryValidDonateList(changeUnit);
//		if (!CollectionUtils.isEmpty(agentList)) {
//			for (DataVo d : agentList) {
//				SysDealDetail dealDetail = new SysDealDetail();
//				dealDetail.setCid(d.getCid());
//				dealDetail.setAgid(d.getAgid());
//				dealDetail.setTotalDonate(d.getDonate());
//				//3.3 每个用户转换后的单元共享值
//				BigDecimal customerUnit = d.getDonate().divide(changeUnit,0,BigDecimal.ROUND_FLOOR);
//				dealDetail.setUnitShare(customerUnit);
//				dealDetail.setType(StaticUtils.AGENT_ACCOUNT_SUM);
//                showUnit = calUtil.add(showUnit,customerUnit,0);
//                logger.info("分红查询代理Cid"+d.getCid());
//				sysDealDetailMapper.insert(dealDetail);
//			}
//		}
//		//3.5 保存显示的单元值与贡献总值
//		BigDecimal showDonate = calUtil.mul(showUnit,changeUnit,0);
//		logger.info("分红总贡献值"+showDonate);
//		logger.info("分红单元共享值"+showUnit);
//		logger.info("分红服务编号"+CalcuUtils.getInstance().getOrderCode(HandleTypeEnums.PLAT_SEND_PROFIT.getPrefix()));
//        dealData.setTotalCal(showDonate);
//        dealData.setUnitCal(showUnit);
//        dealData.setServiceCode(CalcuUtils.getInstance().getOrderCode(HandleTypeEnums.PLAT_SEND_PROFIT.getPrefix()));
//        sysDealDataMapper.insert(dealData);
//		logger.info("每日计算平台交易数据，结束时间：【 " + dateUtil.nowDate(dateUtil.DEFAULT_DATETIME_PATTERN) + " 】");
//	}



	/**
	 * 定时处理解冻金额
	 * @author leehao
	 */
	public void autoHandleFreezingAccount() {
		CalcuUtils calUtil = CalcuUtils.getInstance();
		/* 【1】拿到系统参数 冻结金额解冻天数 */
		int dayTimes = calUtil.getValueByClass(int.class,infoParamService.getValueByCode(ParamEnums.ACCOUNT_AUTO_FREEZE));

		/* 【2】处理线下买单部分的冻结解冻 查询type=2 status=1的数据 */
		this.handleOrderOfflineFreeze(dayTimes);

		/* 【3】处理线上订单冻结解冻 查询订单已完成的 订单详情没有退款且pro_type不为4积分商品的 */
		/* 【4】集合不为空时，对冻结记录进行变更 */
		this.handleOrderOnlineFreeze(dayTimes);

	}
	
	/**
	 * 
	 * 线下订单解冻业务
	 * 买单
	 * @param dayTimes 交易账户冻结时间
	 * @author Wahyee
	 */
	public void handleOrderOfflineFreeze(int dayTimes) {
		//解冻商家金额
		List<BFreezeMoneyDetail> freezeMoneyList = bFreezeMoneyDetailMapper.queryFreezeListByType(dayTimes,
				FreezeStatusEnums.FREEZING.getId(), FreezeTypeEnums.ORDER_OFFLINE_FREEZE.getId());
		if (!CollectionUtils.isEmpty(freezeMoneyList)) {
			for (BFreezeMoneyDetail b : freezeMoneyList) {
				try {
					accountChangeService.handleFreezeBusinessMoney(new FreezeDTO(FreezeStatusEnums.SEND.getId(), b.getPayCode()));
				}catch (Exception e){
					logger.info("【线下解冻】异常："+e.getMessage());
					throw new ThrowJsonException("操作商家冻结金额与金额异常");
				}
			}
		}
		//解冻会员积分
		List<CFreezePointDetail> freezePointList = cFreezePointDetailMapper.queryFreezeListByType(dayTimes,
				FreezeStatusEnums.FREEZING.getId(),FreezeTypeEnums.ORDER_OFFLINE_FREEZE.getId());
		if (!CollectionUtils.isEmpty(freezePointList)) {
			for (CFreezePointDetail c : freezePointList) {
				try {
					accountChangeService.handleFreezeCustomerPoint(new FreezeDTO(FreezeStatusEnums.SEND.getId(), c.getPayCode()) );
				}catch (Exception e){
					logger.info("【线下解冻】异常："+e.getMessage());
					throw new ThrowJsonException("操作用户冻结积分与积分异常");
				}
			}
		}
	}
	
	/**
	 * 
	 * 线上订单解冻业务
	 * @param dayTimes 交易账户冻结时间
	 * @author Wahyee
	 */
	public void handleOrderOnlineFreeze(int dayTimes) {
		Date tempDate = new Date();
		CalcuUtils calUtil = CalcuUtils.getInstance();
		List<CFreezePointDetail> cFreezeList = new ArrayList<CFreezePointDetail>();
		List<BFreezeMoneyDetail> bFreezeList = new ArrayList<BFreezeMoneyDetail>();
		List<CFreezeDonateDetail> cDonateList = new ArrayList<CFreezeDonateDetail>();
		//查询满足解冻条件的订单
		List<FreezeVo> onlineOrderList = orderMainMapper.queryFreezeOnlineOrder(dayTimes);
		List<String> payCodeList = onlineOrderList.stream().map(x -> x.getPayCode()).distinct().collect(Collectors.toList());
		
		//用户冻结积分
		QueryWrapper<CFreezePointDetail> cfpd = new QueryWrapper<CFreezePointDetail>();
		cfpd.in("pay_code", payCodeList);
		cfpd.eq("status", FreezeStatusEnums.FREEZING.getId());
		cfpd.eq("type", FreezeTypeEnums.ORDER_ONLINE_FREEZE.getId());
		List<CFreezePointDetail> cfpdList = cFreezePointDetailMapper.selectList(cfpd);
		//商家冻结金额
		QueryWrapper<BFreezeMoneyDetail> bfmd = new QueryWrapper<BFreezeMoneyDetail>();
		bfmd.in("pay_code", payCodeList);
		bfmd.eq("status", FreezeStatusEnums.FREEZING.getId());
		bfmd.eq("type", FreezeTypeEnums.ORDER_ONLINE_FREEZE.getId());
		List<BFreezeMoneyDetail> cfmdList = bFreezeMoneyDetailMapper.selectList(bfmd);
		//冻结贡献值
		QueryWrapper<CFreezeDonateDetail> cfdd = new QueryWrapper<CFreezeDonateDetail>();
		cfdd.in("pay_code", payCodeList);
		cfdd.eq("status", FreezeStatusEnums.FREEZING.getId());
		cfdd.eq("type", FreezeTypeEnums.ORDER_ONLINE_FREEZE.getId());
		List<CFreezeDonateDetail> bfddList = cFreezeDonateDetailMapper.selectList(cfdd);
		
		//过滤明细
		for(FreezeVo fv : onlineOrderList) {
			//用户冻结积分
			for(CFreezePointDetail d : cfpdList) {
				if(StringUtils.equals(d.getPayCode(), fv.getPayCode()) && calUtil.isEquals(fv.getOrderDetailId(), d.getOrderDetailId()) &&
						calUtil.isEquals(fv.getRefund(),StaticUtils.STATUS_NO )) {
					cFreezeList.add(d);
				}
			}
			//商家冻结金额
			for(BFreezeMoneyDetail d : cfmdList) {
				if(StringUtils.equals(d.getPayCode(), fv.getPayCode()) && calUtil.isEquals(fv.getOrderDetailId(), d.getOrderDetailId()) &&
						calUtil.isEquals(fv.getRefund(),StaticUtils.STATUS_NO )) {
					bFreezeList.add(d);
				}
			}
			//冻结贡献值
			for(CFreezeDonateDetail d : bfddList) {
				if(StringUtils.equals(d.getPayCode(), fv.getPayCode()) && calUtil.isEquals(fv.getOrderDetailId(), d.getOrderDetailId()) &&
						calUtil.isEquals(fv.getRefund(),StaticUtils.STATUS_NO )) {
					cDonateList.add(d);
				}
			}
		}
		
		logger.info("用户积分解冻，用户冻结积分明细ID："+cFreezeList.stream().map(x -> x.getId()).collect(Collectors.toList()));
		for(CFreezePointDetail d : cFreezeList) {
			accountChangeService.handleFreezeCustomerPoint(new FreezeDTO(FreezeStatusEnums.SEND.getId(),d.getOrderDetailId(),2,tempDate));
		}
		logger.info("商家金额解冻，商家冻结金额明细ID："+bFreezeList.stream().map(x -> x.getId()).collect(Collectors.toList()));
		for(BFreezeMoneyDetail d : bFreezeList) {
			accountChangeService.handleFreezeBusinessMoney(new FreezeDTO(FreezeStatusEnums.SEND.getId(),d.getOrderDetailId(),2,tempDate));
		}

	}

	/***
	 * 模式分红
	 */
	public void handleModeBonus(){

		//TODO 任务:模式分红

	}
	
}
